package org.moflon.boardgamegui.view;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.moflon.boardgamegui.controller.GenericController;
import org.moflon.boardgamegui.view.menubar.actions.ExitAction;
import org.moflon.boardgamegui.view.menubar.actions.LoadAction;
import org.moflon.boardgamegui.view.menubar.actions.SaveAction;

public class View<B extends EObject, P extends EObject, F extends EObject>
		extends ApplicationWindow {

	private GenericController<B, P, F> controller;
	private Point size;
	private GUIField<B, P, F>[][] guiBoard;
	private int fieldSize;

	public static <B extends EObject, P extends EObject, F extends EObject> View<B, P, F> createView(
			GenericController<B, P, F> controller, int width, int height) {
		View<B, P, F> view = new View<B, P, F>(controller, width, height);
		view.setBlockOnOpen(true);
		view.create();

		return view;
	}

	@SuppressWarnings("unchecked")
	public View(GenericController<B, P, F> controller, int width, int height) {
		super(null);
		this.addMenuBar();
		this.controller = controller;
		fieldSize = 50;
		guiBoard = new GUIField[height][width];
	}

	protected MenuManager createMenuManager() {
		MenuManager menuBar = new MenuManager("");
		menuBar.setVisible(false);
		MenuManager fileMenu = new MenuManager("&File");
		menuBar.add(fileMenu);
		fileMenu.add(new ExitAction(this));
		fileMenu.add(new LoadAction(this));
		fileMenu.add(new SaveAction(this));

		return menuBar;
	}

	/**
	 * Create contents of the application window.
	 * 
	 * @param parent
	 */
	@Override
	protected Control createContents(Composite parent) {

		Composite container = new Composite(parent, SWT.NONE);
		if (guiBoard.length != 0) {
			GridLayout grLay = new GridLayout(guiBoard[0].length, true);
			grLay.verticalSpacing = 1;
			grLay.horizontalSpacing = 1;
			container.setLayout(grLay);

			for (int y = 0; y < guiBoard.length; y++) {
				for (int x = 0; x < guiBoard[y].length; x++) {
					guiBoard[y][x] = new GUIField<B, P, F>(controller,
							container, fieldSize);
				}
			}
		}
		return container;
	}

	/**
	 * Configure the shell.
	 * 
	 * @param newShell
	 */
	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("Board Game Platform");
		newShell.setLocation(400, 30);
		int height;
		int length;
		if (guiBoard.length == 0) {
			length = 8;
			height = 0;
		} else {
			length = guiBoard[0].length != 0 ? guiBoard[0].length : 2;
			height = guiBoard.length;

		}

		this.size = new Point(length * fieldSize + length * 1 + 25, height
				* fieldSize + height * 1 + 70);

		newShell.setSize(this.size.x, this.size.y);
	}

	/**
	 * Return the initial size of the window.
	 */
	@Override
	protected Point getInitialSize() {
		return new Point((guiBoard.length + 1) * (fieldSize),
				(guiBoard[0].length + 2) * (fieldSize));
	}

	public GUIField<B, P, F> getField(int row, int col) {
		return guiBoard[row][col];
	}

	public GenericController<B, P, F> getController() {
		return controller;
	}
}
